package com.boot.web.util;

import com.boot.json.JacksonTool;
import com.boot.web.http.HttpModel;
import com.boot.web.http.Status;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;
import java.util.Map;

/**
 * @author 霜寒 <1621856595@qq.com>
 * @description HTTP 响应处理工具
 * @date 2020/2/24 11:03
 **/

public class HttpResponseUtil {

    /**
     * @author 霜寒 <1621856595@qq.com>
     * @description 将 ResponseEntity 手动写入 ServletResponse
     * @date 2019/12/4 20:47
     **/
    public static <T> void writeResponse(ServletResponse response, ResponseEntity<T> entity) throws IOException {
        writeResponse(HttpUtil.toHttp(response), entity);
    }

    /**
     * @author 霜寒 <1621856595@qq.com>
     * @description 将 ResponseEntity 手动写入 HttpServletResponse
     * @date 2019/12/4 20:47
     **/
    public static <T> void writeResponse(HttpServletResponse response, ResponseEntity<T> entity) throws IOException {
        response.setContentType("application/json;charset=UTF-8");
        response.setCharacterEncoding("UTF-8");
        response.setStatus(entity.getStatusCodeValue());
        for (Map.Entry<String, List<String>> entry : entity.getHeaders().entrySet()) {
            response.setHeader(entry.getKey(), String.join(",", entry.getValue()));
        }

        if (entity.getBody() != null) {
            String body = JacksonTool.getInstance().writeValueAsString(entity.getBody());
            response.getWriter().print(body);
        }
        response.flushBuffer();
    }

    /**
     * @author 霜寒 <1621856595@qq.com>
     * @description 简化ResponseEntity创建，Response 只包含 http 响应码
     * @date 2019/12/4 20:49
     * @deprecated
     **/
    public static <M> ResponseEntity<M> reply(HttpStatus status) {
        return ResponseEntity.status(status).build();
    }

    /**
     * @author 霜寒 <1621856595@qq.com>
     * @description 简化ResponseEntity创建，Response 只包含 http 响应码和文本消息（消息放入HttpBodyEntity中）
     * @date 2022/1/23 20:12
     * @deprecated
     **/
    public static <M> ResponseEntity<HttpModel<M>> reply(HttpStatus status, String msg) {
        return ResponseEntity.status(status).body(HttpModel.<M>builder().msg(msg).build());
    }

    /**
     * @author 霜寒 <1621856595@qq.com>
     * @description 简化ResponseEntity创建，Response 只包含 http 响应码和数据（数据放入HttpBodyEntity中）
     * @date 2019/12/4 20:51
     * @deprecated
     **/
    public static <M> ResponseEntity<HttpModel<M>> reply(HttpStatus status, M data) {
        return ResponseEntity.status(status).body(HttpModel.<M>builder().data(data).build());
    }

    /**
     * @author 霜寒 <1621856595@qq.com>
     * @description 简化ResponseEntity创建，Response 包含 http 响应码、数据（数据放入HttpBodyEntity中）和文本消息
     * @date 2019/12/4 20:51
     * @deprecated
     **/
    public static <M> ResponseEntity<HttpModel<M>> reply(HttpStatus status, M data, String msg) {
        return ResponseEntity.status(status).body(HttpModel.<M>builder().msg(msg).data(data).build());
    }

    /**
     * @author 霜寒 <1621856595@qq.com>
     * @description 简化ResponseEntity创建，返回200表示成功
     * @date 2019/12/4 20:51
     * @deprecated
     **/
    public static <M> ResponseEntity<M> ok() {
        return ResponseEntity.ok().build();
    }

    /**
     * @author 霜寒 <1621856595@qq.com>
     * @description 简化ResponseEntity创建，返回200表示成功并捎上响应数据
     * @date 2019/12/4 20:52
     * @deprecated
     **/
    public static <M> ResponseEntity<HttpModel<M>> ok(M data) {
        if (data == null) {
            return ok();
        }
        return ResponseEntity.ok(HttpModel.<M>builder().data(data).build());
    }

    /**
     * @author 霜寒 <1621856595@qq.com>
     * @description 简化ResponseEntity创建，返回200表示成功并捎上文本消息
     * @date 2019/12/4 20:52
     * @deprecated
     **/
    public static <M> ResponseEntity<HttpModel<M>> ok(M data, String msg) {
        if (msg == null) {
            return ok();
        }
        return ResponseEntity.ok(HttpModel.<M>builder().msg(msg).data(data).build());
    }

    /**
     * @author 霜寒 <1621856595@qq.com>
     * @description 简化ResponseEntity创建，返回200表示成功并捎上文本消息
     * @date 2023/1/15 20:24
     * @since 3.2.0
     **/
    public static <M> ResponseEntity<HttpModel<M>> OK(@Nonnull String msg) {
        return OK(msg, null);
    }

    /**
     * @author 霜寒 <1621856595@qq.com>
     * @description 简化ResponseEntity创建，返回200表示成功并捎上文本消息
     * @date 2023/1/15 20:24
     * @since 3.2.0
     **/
    public static <M> ResponseEntity<HttpModel<M>> OK(@Nonnull String msg, @Nullable M data) {
        return ResponseEntity.ok(HttpModel.<M>builder().code(Status.SUCCESS.getStatus()).msg(msg).data(data).build());
    }

    /**
     * @author 霜寒 <1621856595@qq.com>
     * @description 简化ResponseEntity创建，返回201表示成功创建或成功修改
     * @date 2019/12/4 20:52
     * @deprecated
     **/
    public static <M> ResponseEntity<M> created() {
        return ResponseEntity.status(HttpStatus.CREATED).build();
    }

    /**
     * @author 霜寒 <1621856595@qq.com>
     * @description 简化ResponseEntity创建，返回201表示成功创建或成功修改并捎上响应数据
     * @date 2019/12/4 20:53
     * @deprecated
     **/
    public static <M> ResponseEntity<HttpModel<M>> created(M data) {
        if (data == null) {
            return created();
        }
        return ResponseEntity.status(HttpStatus.CREATED).body(HttpModel.<M>builder().data(data).build());
    }

    /**
     * @author 霜寒 <1621856595@qq.com>
     * @description 简化ResponseEntity创建，返回201表示成功创建或成功修改并捎上文本消息
     * @date 2019/12/4 20:53
     * @deprecated
     **/

    public static <M> ResponseEntity<HttpModel<M>> created(M data, String msg) {
        if (msg == null) {
            return created();
        }
        return ResponseEntity.status(HttpStatus.CREATED).body(HttpModel.<M>builder().msg(msg).data(data).build());
    }

    /**
     * @author 霜寒 <1621856595@qq.com>
     * @description 简化ResponseEntity创建，返回201表示成功创建或成功修改并捎上文本消息
     * @date 2023/1/15 20:28
     * @since 3.2.0
     **/
    public static <M> ResponseEntity<HttpModel<M>> CREATED(@Nonnull String msg) {
        return CREATED(msg, null);
    }

    /**
     * @author 霜寒 <1621856595@qq.com>
     * @description 简化ResponseEntity创建，返回201表示成功创建或成功修改并捎上文本消息
     * @date 2023/1/15 20:28
     * @since 3.2.0
     **/
    public static <M> ResponseEntity<HttpModel<M>> CREATED(@Nonnull String msg, @Nullable M data) {
        return ResponseEntity.status(HttpStatus.CREATED).body(HttpModel.<M>builder().code(Status.SUCCESS.getStatus()).msg(msg).data(data).build());
    }

    /**
     * @author 霜寒 <1621856595@qq.com>
     * @description 简化ResponseEntity创建，返回204表示没有内容
     * @date 2019/12/4 20:53
     * @deprecated
     **/
    public static <M> ResponseEntity<M> noContent() {
        return ResponseEntity.noContent().build();
    }

    /**
     * @author 霜寒 <1621856595@qq.com>
     * @description 简化ResponseEntity创建，返回204表示没有内容
     * @date 2023/1/15 20:34
     * @since 3.2.0
     **/
    public static <M> ResponseEntity<HttpModel<M>> noContent(@Nonnull String msg) {
        return ResponseEntity.status(HttpStatus.NO_CONTENT).body(HttpModel.<M>builder().code(Status.NO_RESOURCE.getStatus()).msg(msg).build());
    }

    /**
     * @author 霜寒 <1621856595@qq.com>
     * @description 简化ResponseEntity创建，返回400表示请求参数有问题
     * @date 2019/12/4 20:54
     * @deprecated
     **/
    public static <M> ResponseEntity<M> badRequest() {
        return ResponseEntity.badRequest().build();
    }

    /**
     * @author 霜寒 <1621856595@qq.com>
     * @description 简化ResponseEntity创建，返回400表示请求参数有问题并捎上文本消息
     * @date 2019/12/4 20:55
     **/
    public static <M> ResponseEntity<HttpModel<M>> badRequest(@Nonnull String msg) {
        return badRequest(msg, null);
    }

    /**
     * @author 霜寒 <1621856595@qq.com>
     * @description 简化ResponseEntity创建，返回400表示请求参数有问题并捎上响应数据
     * @date 2019/12/4 20:55
     **/
    public static <M> ResponseEntity<HttpModel<M>> badRequest(@Nonnull String msg, @Nullable M data) {
        return ResponseEntity.badRequest().body(HttpModel.<M>builder().msg(msg).data(data).build());
    }

    /**
     * @author 霜寒 <1621856595@qq.com>
     * @description 简化ResponseEntity创建，返回401表示登录失败或者身份验证未通过
     * @date 2019/12/4 20:56
     * @deprecated
     **/
    public static <M> ResponseEntity<M> unAuthorized() {
        return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build();
    }

    /**
     * @author 霜寒 <1621856595@qq.com>
     * @description 简化ResponseEntity创建，返回401并携带文本信息表示登录失败或者身份验证未通过
     * @date 2020/2/14 19:38
     **/
    public static <M> ResponseEntity<HttpModel<M>> unAuthorized(String msg) {
        return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(HttpModel.<M>builder().msg(msg).build());
    }

    /**
     * @author 霜寒 <1621856595@qq.com>
     * @description 简化ResponseEntity创建，返回403表示鉴权失败
     * @date 2019/12/4 20:56
     * @deprecated
     **/
    public static <M> ResponseEntity<M> forbidden() {
        return ResponseEntity.status(HttpStatus.FORBIDDEN).build();
    }

    /**
     * @author 霜寒 <1621856595@qq.com>
     * @description 简化ResponseEntity创建，返回403并携带文本信息表示鉴权失败
     * @date 2020/2/14 19:38
     **/
    public static <M> ResponseEntity<HttpModel<M>> forbidden(String msg) {
        return ResponseEntity.status(HttpStatus.FORBIDDEN).body(HttpModel.<M>builder().msg(msg).build());
    }

    /**
     * @author 霜寒 <1621856595@qq.com>
     * @description 简化ResponseEntity创建，返回404表示无法找到资源
     * @date 2019/12/4 20:56
     * @deprecated
     **/
    public static <M> ResponseEntity<M> notFound() {
        return ResponseEntity.notFound().build();
    }

    /**
     * @author 霜寒 <1621856595@qq.com>
     * @description 简化ResponseEntity创建，返回404表示无法找到资源并捎上文本消息
     * @date 2019/12/4 20:56
     **/
    public static <M> ResponseEntity<HttpModel<M>> notFound(String msg) {
        return notFound(msg, null);
    }

    /**
     * @author 霜寒 <1621856595@qq.com>
     * @description 简化ResponseEntity创建，返回404表示无法找到资源并捎上响应数据
     * @date 2019/12/4 20:56
     **/
    public static <M> ResponseEntity<HttpModel<M>> notFound(@Nonnull String msg, @Nullable M data) {
        return ResponseEntity.status(HttpStatus.NOT_FOUND).body(HttpModel.<M>builder().code(Status.NO_RESOURCE.getStatus()).msg(msg).build());
    }

    /**
     * @author 霜寒 <1621856595@qq.com>
     * @description 存在data就返回200，否则401
     * @date 2019/12/4 20:57
     * @deprecated
     **/
    public static <M> ResponseEntity<HttpModel<M>> okOrUnauthorized(M data) {
        if (data == null) {
            return unAuthorized();
        }
        return ResponseEntity.ok(HttpModel.<M>builder().data(data).build());
    }

    /**
     * @author 霜寒 <1621856595@qq.com>
     * @description 存在token就返回200并在响应头里插入token，否则401
     * @date 2019/12/4 20:57
     * @deprecated
     **/
    public static <M> ResponseEntity<M> okOrUnauthorized(String header, String token) {
        if (token == null) {
            return unAuthorized();
        }
        return ResponseEntity.ok().header(header, token).build();
    }

    /**
     * @author 霜寒 <1621856595@qq.com>
     * @description 只有当data与token都存在时返回200并捎上数据和token，否则401
     * @date 2019/12/4 20:58
     * @deprecated
     **/
    public static <M> ResponseEntity<HttpModel<M>> okOrUnauthorized(M data, String token) {
        if (data == null || token == null) {
            return unAuthorized();
        } else {
            return ResponseEntity.status(HttpStatus.OK)
                    .header("token", token)
                    .body(HttpModel.<M>builder().data(data).build());
        }
    }

    /**
     * @author 霜寒 <1621856595@qq.com>
     * @description 存在data就返回200，否则404
     * @date 2019/12/4 20:58
     * @deprecated
     **/
    public static <M> ResponseEntity<HttpModel<M>> okOrNotFound(M data) {
        if (data == null) {
            return notFound();
        }
        return ResponseEntity.ok(HttpModel.<M>builder().data(data).build());
    }

    /**
     * @author 霜寒 <1621856595@qq.com>
     * @description 存在data就返回200，否则返回204
     * @date 2021/3/19 14:46
     * @deprecated
     **/
    public static <M> ResponseEntity<HttpModel<M>> okOrNoContent(M data) {
        if (data == null) {
            return noContent();
        }
        return ResponseEntity.ok(HttpModel.<M>builder().data(data).build());
    }

    /**
     * @author 霜寒 <1621856595@qq.com>
     * @description 存在data就返回200，否则返回204
     * @date 2021/3/19 14:46
     * @deprecated
     **/
    public static <M> ResponseEntity<M> createdOrBadRequest(boolean isSuccess) {
        if (isSuccess) {
            return created();
        } else {
            return badRequest();
        }
    }

    /**
     * @author 霜寒 <1621856595@qq.com>
     * @description 返回204表示成功删除，返回404表示没有找到记录
     * @date 2019/12/4 20:53
     * @deprecated
     **/
    public static <M> ResponseEntity<M> noContentOrNotFound(boolean isSuccess) {
        if (isSuccess) {
            return noContent();
        } else {
            return notFound();
        }
    }

    /**
     * @author 霜寒 <1621856595@qq.com>
     * @description 简化ResponseEntity创建，返回500表示服务器出现错误
     * @date 2020/2/13 18:24
     * @deprecated
     **/
    public static <M> ResponseEntity<M> serverError() {
        return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
    }

    /**
     * @author 霜寒 <1621856595@qq.com>
     * @description 简化ResponseEntity创建，返回500表示服务器出现错误并捎上文本消息
     * @date 2019/12/4 20:55
     **/
    public static <M> ResponseEntity<HttpModel<M>> serverError(@Nonnull String msg) {
        return serverError(msg, null);
    }

    /**
     * @author 霜寒 <1621856595@qq.com>
     * @description 简化ResponseEntity创建，返回500表示服务器出现错误并捎上响应数据
     * @date 2019/12/4 20:55
     **/
    public static <M> ResponseEntity<HttpModel<M>> serverError(@Nonnull String msg, @Nullable M data) {
        return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(HttpModel.<M>builder().msg(msg).data(data).build());
    }

    public static <T> boolean isOk(ResponseEntity<T> entity) {
        return entity.getStatusCodeValue() == 200;
    }

    public static <T> boolean isCreated(ResponseEntity<T> entity) {
        return entity.getStatusCodeValue() == 201;
    }

    public static <T> boolean isNoContent(ResponseEntity<T> entity) {
        return entity.getStatusCodeValue() == 204;
    }

    public static <T> boolean isBadRequest(ResponseEntity<T> entity) {
        return entity.getStatusCodeValue() == 400;
    }

    public static <T> boolean isUnauthorized(ResponseEntity<T> entity) {
        return entity.getStatusCodeValue() == 401;
    }

    public static <T> boolean isForbidden(ResponseEntity<T> entity) {
        return entity.getStatusCodeValue() == 403;
    }

    public static <T> boolean isNotFound(ResponseEntity<T> entity) {
        return entity.getStatusCodeValue() == 404;
    }

    public static <T> T getBody(ResponseEntity<T> entity) {
        return entity.getBody();
    }

    public static <T> HttpHeaders getHeaders(ResponseEntity<T> entity) {
        return entity.getHeaders();
    }

    public static <T> String getHeader(ResponseEntity<T> entity, String headerName) {
        HttpHeaders headers = entity.getHeaders();
        return headers.getFirst(headerName);
    }

    public static <M> Integer getCode(ResponseEntity<HttpModel<M>> responseEntity) {
        HttpModel<M> model = responseEntity.getBody();
        if (model == null) {
            return null;
        } else {
            return model.getCode();
        }
    }

    public static <M> String getMessage(ResponseEntity<HttpModel<M>> responseEntity) {
        HttpModel<M> model = responseEntity.getBody();
        if (model == null) {
            return null;
        } else {
            return model.getMsg();
        }
    }

    public static <M> M getData(ResponseEntity<HttpModel<M>> responseEntity) {
        HttpModel<M> model = responseEntity.getBody();
        if (model == null) {
            return null;
        } else {
            return model.getData();
        }
    }

}
